package io.gitee.mingbaobaba.apijson.querycondition.query.dao.impl;

import io.gitee.mingbaobaba.apijson.querycondition.query.dao.DwQueryDao;
import io.gitee.mingbaobaba.apijson.querycondition.query.exception.ConditionException;
import io.gitee.mingbaobaba.apijson.querycondition.query.properties.ApiJsonQueryProperties;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.StringUtils;


import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>默认基于http方式获取数据接口实现</p>
 *
 * @author yingsheng.ye
 * @version 1.0.0
 * @since 2023/6/27 20:40
 */
@Slf4j
public class DefaultHttpApiJsonQueryDaoImpl implements DwQueryDao {
    private final ApiJsonQueryProperties dataWarehouseProperties;

    private final Random rand = new Random();

    public DefaultHttpApiJsonQueryDaoImpl(ApiJsonQueryProperties dataWarehouseProperties) {
        this.dataWarehouseProperties = dataWarehouseProperties;
    }

    @SneakyThrows
    @Override
    public String getData(Map<String, Object> params, String biSigns) {
        StringBuilder logBuilder = new StringBuilder();
        logBuilder.append("\033[36m\n\n---------------------------------------------------------------\n");
        String url = loadBalanceUrl(dataWarehouseProperties.getServiceUrl());
        String token = getToken();
        String jsonParam = JSON.toJSONString(params);
        logBuilder.append("请求查询服务token：").append(token).append("\n");
        logBuilder.append("请求查询服务地址：").append(url).append("\n");
        logBuilder.append("请求查询业务标识：").append(biSigns).append("\n");
        logBuilder.append("请求查询服务参数：").append(jsonParam).append("\n");
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(jsonParam, mediaType);
        Request request = new Request.Builder().url(url)
                .addHeader("Authorization", token)
                .addHeader("biSigns", biSigns)
                .post(body)
                .build();
        Response res = client.newCall(request).execute();
        if (!res.isSuccessful()) {
            throw new ConditionException("调用接口返回异常:" + res.message());
        }
        logBuilder.append("请求查询服务结果：").append(res).append("\n");
        logBuilder.append("---------------------------------------------------------------\n\033[0m");
        if (log.isDebugEnabled()) {
            log.debug(logBuilder.toString());
        }
        JSONObject data = resultToObject(Objects.requireNonNull(res.body()).toString());
        return JSON.toJSONString(data);
    }

    /**
     * 获取token
     *
     * @return token值
     */
    private String getToken() throws IOException {
        Map<String, Object> params = new HashMap<>(4);
        params.put("client_id", dataWarehouseProperties.getClientId());
        params.put("client_secret", dataWarehouseProperties.getClientSecret());
        params.put("grant_type", dataWarehouseProperties.getGrantType());
        params.put("scope", dataWarehouseProperties.getScope());
        OkHttpClient client = new OkHttpClient();
        MediaType mediaType = MediaType.parse("application/json; charset=utf-8");
        RequestBody body = RequestBody.create(JSON.toJSONString(params), mediaType);
        Request request = new Request.Builder().url(loadBalanceUrl(dataWarehouseProperties.getTokenUrl()))
                .post(body)
                .build();
        Response res = client.newCall(request).execute();
        if (!res.isSuccessful()) {
            throw new ConditionException("调用接口返回异常:" + res.message());
        }
        JSONObject data = resultToObject(Objects.requireNonNull(res.body()).toString());
        String accessToken = data.getString("access_token");
        return "Bearer " + accessToken;
    }

    /**
     * 结果提取转换
     *
     * @param res 返回结果
     * @return JSONObject
     */
    private JSONObject resultToObject(String res) {
        if (StringUtils.isBlank(res)) {
            throw new ConditionException("调用查询服务返回为空");
        }
        //解析token
        JSONObject jsonObject = JSON.parseObject(res);
        int successCode = 20000;
        int code = jsonObject.getInteger("code");
        if (successCode != code) {
            throw new ConditionException("调用查询服务异常：" + jsonObject.getString("message"));
        }
        return jsonObject.getJSONObject("data");
    }


    /**
     * 获取服务请求地址
     *
     * @return 地址
     */
    private String loadBalanceUrl(String url) {
        List<String> urlList = Stream.of(url.split(",")).collect(Collectors.toList());
        int size = urlList.size();
        //地址数量为1个，直接返回
        if (size == 1) {
            return urlList.get(0);
        }
        int idx = rand.nextInt(size);
        return urlList.get(idx);
    }
}
